package com.nwpu.hass.controller;

import com.nwpu.hass.domain.DeviceEntity;
import com.nwpu.hass.domain.JsonRequest.*;
import com.nwpu.hass.domain.JsonResponse.ApplyEntity;
import com.nwpu.hass.domain.JsonResponse.IdleDevicesGroupResponse;
import com.nwpu.hass.service.RedisService;
import com.nwpu.hass.service.RegisterformService;
import com.nwpu.hass.serviceimpl.QRCodeService;
import com.nwpu.hass.utils.MyResponseEntity;
import com.nwpu.hass.service.DeviceService;
import com.nwpu.hass.utils.Code;
import com.nwpu.hass.utils.ScheduleCheckDevice;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.relational.core.sql.In;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.Objects;

/**
 * 设备Controller
 *
 * @author wjy
 * @version v1.1.0
 */
@Slf4j
@RestController
@RequestMapping(value = "/device")
public class DeviceController {

    @Resource
    DeviceService deviceService;
    @Resource
    RegisterformService registerformService;
    @Autowired
    RedisService redisService;

    @Value("${filepath}")
    private String test;

    private static final Logger logger = LoggerFactory.getLogger(DeviceController.class);

    /**
     * 获取所有设备列表
     */
    @GetMapping(value = "/")
    public MyResponseEntity< List<DeviceEntity> > getAllDevices(@RequestParam("pageNo")Integer pageNo) {
        List<DeviceEntity> deviceEntities = deviceService.getAllDevice(pageNo);
        log.info("已获取所有设备列表");
        return new MyResponseEntity<>(Code.OK,deviceEntities);
    }

    /**
     * 获取某一设备详情
     */
    @GetMapping(value = "/info/{deviceId")
    public MyResponseEntity<DeviceEntity> getOneDevice(@PathVariable long deviceId) {
        DeviceEntity deviceEntity = deviceService.getOneDeviceInfo(deviceId);
        if(Objects.isNull(deviceEntity)) {
            return new MyResponseEntity<>(Code.ERROR, "错误的设备ID", null);
        }
        log.info("获取设备ID为" + deviceId + "的设备信息");
        return new MyResponseEntity<>(deviceEntity);
    }

    /**
     * 归还申请列表
     * @return 归还申请列表
     */
    @GetMapping(value = "/useChecks/return")
    public MyResponseEntity<List<ApplyEntity>> useChecksReturn(@RequestParam("pageNo") Integer pageNo) {
        List<ApplyEntity> applies = deviceService.useChecksReturnList(pageNo);
        log.info("已获取所有归还申请列表");
        return new MyResponseEntity<>(Code.OK, Code.OK.getMsg(), applies);
    }

    /**
     * 借出申请列表
     * @return 借出申请列表
     */
    @GetMapping(value = "/useChecks/borrow")
    public MyResponseEntity<List<ApplyEntity>> useChecksBorrow(@RequestParam("pageNo") Integer pageNo) {
        List<ApplyEntity> applies = deviceService.useChecksBorrowList(pageNo);
        log.info("已获取所有借出申请列表");
        return new MyResponseEntity<>(Code.OK, Code.OK.getMsg(), applies);
    }

    /**
     * 借出设备
     */
    @PostMapping(value = "/applyBorrow")
    public MyResponseEntity<Object> borrowDevice(@RequestHeader("token") String token,
                               @RequestBody @Valid IdleDeviceRequest request) {
        Long userId = redisService.getUserId(token);
        DeviceEntity deviceEntity = deviceService.idleDevice(request.getType(), request.getFamily(), request.getDeviceName(), userId);

        if(deviceEntity == null) {
            log.info("当前没有空闲设备");
            return new MyResponseEntity<>(Code.ERROR, "没有空闲设备", null);
        } else {
            log.info("设备已借出");
            return new MyResponseEntity<>(null);
        }
    }

    /**
     * 归还设备
     */
    @GetMapping(value = "/return/{returnId}")
    public MyResponseEntity<Object> lendDevice(@RequestHeader("token") String token,
                                               @PathVariable String returnId) {
        long rid;
        try {
            rid = Long.parseLong(returnId);
        } catch (NumberFormatException nfe) {
            return new MyResponseEntity<>(Code.ERROR,"参数错误，设备id为long类型", null);
        }
        Long userId = redisService.getUserId(token);
        DeviceEntity deviceEntity = deviceService.returnDevice(userId,rid);
        if(deviceEntity == null) {
            return new MyResponseEntity<>(Code.ERROR, "id对应的设备不存在", null);
        } else {
            log.info("设备已归还" + "归还ID为 " + returnId);
            return new MyResponseEntity<>(null);
        }
    }

    /**
     * 获取某一条借出/归还申请
     */
    @GetMapping("/useChecks/{checkId}")
    public MyResponseEntity<ApplyEntity> getOneApply(@PathVariable String checkId) {
        long cid;
        try {
            cid = Long.parseLong(checkId);
        } catch (NumberFormatException nfe) {
            return new MyResponseEntity<>(Code.BAD_OPERATION, "记录id必须为数字", null);
        }
        log.info("已获取设备借出，归还信息");
        return new MyResponseEntity<>(Code.OK, registerformService.findOneRegisterById(cid));
    }

    /**
     * 审核一条借出归还申请
     */
    @PostMapping("/checkRegister")
    public MyResponseEntity<Object> processApply(@RequestBody @Valid ProcessApplyRequest request) throws Exception {
        DeviceEntity deviceEntity = registerformService.checkOneRegisterById(request.getId(), request.isPass());
        if(deviceEntity == null) {
            return new MyResponseEntity<>(Code.ERROR, "不存在这条id记录",null);
        }
        if(ScheduleCheckDevice.isBroken(deviceEntity)){
            deviceService.sendMailAndWeChat(String.valueOf(deviceEntity.getDeviceId()));
        }
        log.info("审核通过借出归还申请，" + "申请ID为 " + request.getId());
        return new MyResponseEntity<>(null);
    }

    @GetMapping("/idleDevices")
    public MyResponseEntity<List<IdleDevicesGroupResponse>> idleDevices(@RequestParam("pageNo") Integer pageNo){
        List<IdleDevicesGroupResponse> responses = deviceService.getAllIdleDeviceGroup(pageNo*7-7,7);
        log.info("当前空闲设备已获取");
        return new MyResponseEntity<>(Code.OK,responses);
    }

    /**
     * 给设备分配位置
     */
    @PostMapping(value = "/assignPosition")
    public MyResponseEntity<Object> assignosition(@RequestBody @Valid AssignPosition request) {
        DeviceEntity deviceEntity = deviceService.getDeviceById(request.getDeviceId());
        if(Objects.isNull(deviceEntity)){
            return new MyResponseEntity<>(Code.ERROR,"不存在id为此的设备",null);
        }
        deviceEntity.setPosition(request.getPosition());
        deviceService.updateDevice(deviceEntity);
        log.info("管理已为设备分配好位置");
        return new MyResponseEntity<>(Code.OK, null);
    }

    @PostMapping("modifyInfo")
    public MyResponseEntity<Object> modifyInfo(@RequestBody @Valid ModifyInfoRequestBody request){
        DeviceEntity deviceEntity = new DeviceEntity();
        BeanUtils.copyProperties(request,deviceEntity);
        deviceService.updateDevice(deviceEntity);
        log.info("设备信息修改成功");
        return new MyResponseEntity<>(null);
    }

    @PostMapping("handlescrap")
    public MyResponseEntity<Object> handleScrap(@RequestBody @Valid HandleScrapRequestBody request){
        DeviceEntity deviceEntity = deviceService.getDeviceById(request.getDeviceId());
        if(Objects.isNull(deviceEntity)){
            return new MyResponseEntity<>(Code.BAD_OPERATION,"设备不存在",null);
        }
        if(request.isPass()){
            deviceEntity.setStatus(4);
        }else{
            deviceEntity.setStatus(0);
        }
        deviceService.updateDevice(deviceEntity);
        return new MyResponseEntity<>(null);
    }

    @GetMapping("lend")
    public MyResponseEntity<ApplyEntity> queryLendInfo(@RequestParam(value="recordId",required = true)Long recordId){
        ApplyEntity applyEntity = registerformService.findOneRegisterById(recordId);
        log.info("借出信息已获取");
        return new MyResponseEntity<ApplyEntity>(Code.OK,applyEntity);
    }

    @GetMapping("borrow")
    public MyResponseEntity<Object> borrowedDevice(@RequestHeader("token") String token,@RequestParam("pageNo") Integer pageNo){
        Long userId = redisService.getUserId(token);
        List<DeviceEntity> deviceEntities = deviceService.getAllBorrowedDevice(userId,pageNo);
        log.info("借出信息已获取");
        return new MyResponseEntity<>(Code.OK,deviceEntities);
    }

    @PostMapping("checkIn")
    public MyResponseEntity<Object> checkIn(@RequestHeader("token") String token,
                                            @RequestParam("execelfile") MultipartFile file) {
        log.info("test va" + test);
        Long userId = redisService.getUserId(token);
        deviceService.checkInDevices(userId, file);
        log.info("用户已上传设备信息");
        return new MyResponseEntity<>(null);
    }

    /**
     * 获取所有待添加（没有位置）的设备
     */
    @GetMapping("/addDevice")
    public MyResponseEntity<Object> noPosDevices(@RequestParam ("pageNo") int pageNo) {

        List<DeviceEntity> deviceEntities;
        deviceEntities = deviceService.getNoPosDevices(pageNo);
        log.info("已获取所有待添加的设备");
        return new MyResponseEntity<>(deviceEntities);
    }

    @PostMapping("/barcode")
    @ResponseBody
    public void generateBarcodePdf(HttpServletResponse response,@RequestBody DeviceEntity[] deviceEntities) throws Exception {
        // 注意处理前端传送的json数组的方式
        File pdf = QRCodeService.generateQRCodePdf(deviceEntities);
        FileInputStream fileInputStream = new FileInputStream(pdf);
        ServletOutputStream os = response.getOutputStream();
        response.setContentType("multipart/form-data");
        // 读取文件流
        int len = 0;
        byte[] buffer = new byte[1024];
        while((len = fileInputStream.read(buffer))!=-1){
            os.write(buffer,0,len);
        }
        os.flush();
        os.close();
        fileInputStream.close();
        pdf.delete();
        log.info("二维码已生成");
    }

    @GetMapping("checkstatus")
    public MyResponseEntity<Object> checkBorrowState(@RequestHeader("token") String token,@RequestParam("status") int status){
        Long userId = redisService.getUserId(token);
        log.info("检测设备状态");
        return new MyResponseEntity<>(deviceService.getOnDevices(userId,status));
    }

    @GetMapping("scraps")
    public MyResponseEntity<Object> getScrapedDevices(@RequestParam("pageNo") int pageNo){
        return new MyResponseEntity<>(deviceService.getDevicesByStatusPageNo(pageNo));
    }
}
